#include <iostream>
#include <cstring>
#include <thread>

#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>

#include "common.h"

using namespace std;

const int MAX_SIZE = 65535;


void NewConsole(int fd){
    while(true){
        // 6. 与客户端通信
        char buffer[MAX_SIZE] = {0};
        memset(buffer, 0, MAX_SIZE);
        ssize_t ret = read(fd, buffer, sizeof(buffer));
        if(ret <= 0){
            std::cout << "连接断开:" << fd << std::endl;
            close(fd);
            break;
        }else{
            std::cout << buffer << std::endl;
        }
    }
}

int StartConsole(){
    // 1. 创建 socket
    int server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd == -1) {
        std::cerr << "Socket creation failed\n";
        return 1;
    }

    // 2. 配置地址和端口
    sockaddr_in address;
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY; // 监听所有网络接口
    address.sin_port = htons(common::CONSOLE_PORT);       // 端口号

    int opt = 1;
    int result = setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(opt));
    if(result == -1){
        std::cerr << "socket SO_REUSEADDR error\n";
        return 1;
    }

    int nagle_status = 0;
    result = setsockopt(server_fd, IPPROTO_TCP, TCP_NODELAY, (const void *)&nagle_status, sizeof(nagle_status));
    if(result == -1){
        std::cerr << "socket TCP_NODELAY error\n";
        return 1;
    }

    // 3. 绑定 socket
    if (bind(server_fd, (sockaddr*)&address, sizeof(address)) < 0) {
        std::cerr << "Bind failed\n";
        return 1;
    }

    // 4. 开始监听
    if (listen(server_fd, 3) < 0) { // 允许3个连接排队
        std::cerr << "Listen failed\n";
        return 1;
    }

    std::cout << "StartConsole...\n";

    // 5. 接受客户端连接
    sockaddr_in client_addr;
    socklen_t client_addr_len = sizeof(client_addr);
    while(true){
        int client_fd = accept(server_fd, (sockaddr*)&client_addr, &client_addr_len);
        if (client_fd < 0) {
            std::cerr << "Accept failed\n";
            return 1;
        }

        std::cout << "Client connected\n";

        thread t(NewConsole, client_fd);
        t.detach();
    }
}


int main(int argc, char const *argv[])
{
    StartConsole();
    return 0;
}
